from D5Core.Details.D5Api import *
from D5Core.D5Common import *
import json



class D5Model:
    
    """
    D5Model 类是D5中所有模型的基类，提供了模型的基本属性和操作方法。
    
    该类封装了与模型相关的属性如位置、旋转、缩放等，并提供了对这些属性的访问和修改方法。

    Attributes:
        name (str): 模型的名称
        location (Vector3): 模型的位置坐标
        rotation (Vector3): 模型的旋转角度
        scale (Vector3): 模型的缩放比例
        hide (bool): 模型的隐藏状态
        lock (bool): 模型的锁定状态
        is_scale_locked (bool): 模型的缩放锁定状态
        is_visible_in_video (bool): 模型在视频中的可见性状态
        size (Vector3): 模型的当前尺寸
        original_size (Vector3): 模型的原始尺寸
        object_type (D5ApiActorType): 模型的对象类型
    """

    _attrs = {
        'name': {
            'from': str,
            'to': str,
            'default': ''
        },
        'location': {
            'from': Vector3.from_str,
            'to': Vector3.to_str,
            'default': '0,0,0'
        },
        'rotation': {
            'from': Rotator.from_str,
            'to': Rotator.to_str,
            'default': '0,0,0'
        },
        'scale': {
            'from': Vector3.from_str,
            'to': Vector3.to_str,
            'default': '0,0,0'
        },
        'hide': {
            'from': lambda x: x.lower() == 'true' if isinstance(x, str) else bool(x),
            'to': lambda x: str(x).lower(),
            'default': False
        },
        'lock': {
            'from': lambda x: x.lower() == 'true' if isinstance(x, str) else bool(x),
            'to': lambda x: str(x).lower(),
            'default': False
        },
        'is_scale_locked': {
            'from': lambda x: x.lower() == 'true' if isinstance(x, str) else bool(x),
            'to': lambda x: str(x).lower(),
            'default': False
        },
        'is_visible_in_video': {
            'from': lambda x: x.lower() == 'true' if isinstance(x, str) else bool(x),
            'to': lambda x: str(x).lower(),
            'default': False
        },
        'size': {
            'from': Vector3.from_str,
            'to': Vector3.to_str,
            'default': '0,0,0'
        },
        'original_size': {
            'from': Vector3.from_str,
            'to': Vector3.to_str,
            'default': '0,0,0'
        },
        "object_type":{
            "from":D5ApiActorType.from_str,
            "to":D5ApiActorType.to_str,
            "default":D5ApiActorType.NoType.to_str()
        }
    }

    def __init__(self, dict_data):
        """
        初始化模型实例。
        
        :param dict_data: 包含模型属性的字典数据
        :type dict_data: dict
        """
        self._unique_actor_id = dict_data.get("unique_actor_id", "")
        # 动态初始化属性
        for attr, config in self._attrs.items():
            value = dict_data.get(attr, config['default'])
            converted_value = config['from'](value)
            setattr(self, f'__{attr}', converted_value)

    @staticmethod
    def __change_value(unique_actor_id:str,attribute:str,value:str,event:str):
        
        d5api = D5Api()
        req_id = d5api.generate_uuid()

        payload = {
            "uuid": req_id,
            "type": APIRequestType.WRITE_ORDINARY_ATTRIBUTE.value,
            "content": """
            {
                "ActorId": "%s",
                "Param": "%s",
                "Value": "%s",
                "Event": "%s"
            }
            """%(unique_actor_id,attribute,value,event)
        }
        return d5api.request_sync(req_id,json.dumps(payload))
     

    @staticmethod
    def __read_value(unique_actor_id:str,attribute:str):
        d5api = D5Api()
        req_id = d5api.generate_uuid()

        payload = {
            "uuid": req_id,
            "type": APIRequestType.READ_ORDINARY_ATTRIBUTE.value,
            "content": """
            {
                "ActorId": "%s",
                "Param": "%s"
            }
            """%(unique_actor_id,attribute)
        }
        return d5api.request_sync(req_id,json.dumps(payload))

    @classmethod
    def _generate_methods(cls):
        """
        为类动态生成getter和setter方法。
        
        该方法遍历类的_attrs字典，为每个属性生成对应的getter和setter方法。
        """
        for attr in cls._attrs:
            # 生成getter方法
            def getter(self, attr=attr):
                res = self.__read_value(self._unique_actor_id, attr)
                content = json.loads(res).get("content", "{}")
                dict_data = json.loads(content).get(self._unique_actor_id, {})
                value_str = dict_data.get(attr, self._attrs[attr]['default'])
                value = self._attrs[attr]['from'](value_str)
                setattr(self, f'__{attr}', value)
                return value
            getter_name = f'get_{attr}'
            setattr(cls, getter_name, getter)

            # 生成setter方法
            def setter(self, value, event=APIEvent.NOW,attr=attr):
                value_str = self._attrs[attr]['to'](value)
                res = self.__change_value(self._unique_actor_id, attr, value_str, event)
                setattr(self, f'__{attr}', value)
                # 解析返回值，检查是否成功
                content = json.loads(res).get("content", "{}")
                dict_data = json.loads(content).get("ApiRet", {})
                return dict_data.get("success", False)

            setter_name = f'set_{attr}'
            setattr(cls, setter_name, setter)
    
    
    def get_unique_actor_id(self) ->str:
        """
        获取模型的唯一标识符ID。
        
        :return: 模型的唯一标识符
        :rtype: str
        """
        return self._unique_actor_id
    
    def get_name(self) -> str:
        """
        获取模型的名称。
        
        :return: 模型的名称
        :rtype: str
        """
        ...
    
    def set_name(self, value: str, event: str = APIEvent.NOW) -> bool:
        """
        设置模型的名称。
        
        :param value: 新的模型名称
        :type value: str
        :param event: 事件类型，默认为立即执行
        :type event: str
        :return: 操作是否成功
        :rtype: bool
        """
        ...
    
    def get_location(self) -> Vector3:
        """
        获取模型的位置坐标。
        
        :return: 模型的位置坐标(x,y,z)
        :rtype: Vector3
        """
        ...
    
    def set_location(self, value: Vector3, event: str = APIEvent.NOW) -> bool:
        """
        设置模型的位置坐标。
        
        :param value: 新的位置坐标
        :type value: Vector3
        :param event: 事件类型，默认为立即执行
        :type event: str
        :return: 操作是否成功
        :rtype: bool
        """
        ...
    
    def get_rotation(self) -> Vector3:
        """
        获取模型的旋转角度。
        
        :return: 模型的旋转角度(x,y,z)
        :rtype: Vector3
        """
        ...
    
    def set_rotation(self, value: Vector3, event: str = APIEvent.NOW) -> bool:
        """
        设置模型的旋转角度。
        
        :param value: 新的旋转角度
        :type value: Vector3
        :param event: 事件类型，默认为立即执行
        :type event: str
        :return: 操作是否成功
        :rtype: bool
        """
        ...
    
    def get_scale(self) -> Vector3:
        """
        获取模型的缩放比例。
        
        :return: 模型的缩放比例(x,y,z)
        :rtype: Vector3
        """
        ...
    
    def set_scale(self, value: Vector3, event: str = APIEvent.NOW) -> bool:
        """
        设置模型的缩放比例。
        
        :param value: 新的缩放比例
        :type value: Vector3
        :param event: 事件类型，默认为立即执行
        :type event: str
        :return: 操作是否成功
        :rtype: bool
        """
        ...

    def get_hide(self) -> bool:
        """
        获取模型的隐藏状态。
        
        :return: 模型是否隐藏
        :rtype: bool
        """
        ...
    
    def set_hide(self, value: bool, event: str = APIEvent.NOW) -> bool:
        """
        设置模型的隐藏状态。
        
        :param value: 新的隐藏状态
        :type value: bool
        :param event: 事件类型，默认为立即执行
        :type event: str
        :return: 操作是否成功
        :rtype: bool
        """
        ...
    
    def get_lock(self) -> bool:
        """
        获取模型的锁定状态。
        
        :return: 模型是否锁定
        :rtype: bool
        """
        ...
    
    def set_lock(self, value: bool, event: str = APIEvent.NOW) -> bool:
        """
        设置模型的锁定状态。
        
        :param value: 新的锁定状态
        :type value: bool
        :param event: 事件类型，默认为立即执行
        :type event: str
        :return: 操作是否成功
        :rtype: bool
        """
        ...
    
    def get_is_scale_locked(self) -> bool:
        """
        获取模型的缩放锁定状态。
        
        :return: 模型的缩放是否锁定
        :rtype: bool
        """
        ...
    
    def set_is_scale_locked(self, value: bool, event: str = APIEvent.NOW) -> bool:
        """
        设置模型的缩放锁定状态。
        
        :param value: 新的缩放锁定状态
        :type value: bool
        :param event: 事件类型，默认为立即执行
        :type event: str
        :return: 操作是否成功
        :rtype: bool
        """
        ...
    
    def get_is_visible_in_video(self) -> bool:
        """
        获取模型在视频中的可见性状态。
        
        :return: 模型在视频中是否可见
        :rtype: bool
        """
        ...
    
    def set_is_visible_in_video(self, value: bool, event: str = APIEvent.NOW) -> bool:
        """
        设置模型在视频中的可见性状态。
        
        :param value: 新的视频可见性状态
        :type value: bool
        :param event: 事件类型，默认为立即执行
        :type event: str
        :return: 操作是否成功
        :rtype: bool
        """
        ...
    
    def get_size(self) -> Vector3:
        """
        获取模型的当前尺寸。
        
        :return: 模型的尺寸(宽,高,深)
        :rtype: Vector3
        """
        ...
    
    def set_size(self, value: Vector3, event: str = APIEvent.NOW) -> bool:
        """
        设置模型的尺寸。
        
        :param value: 新的尺寸值
        :type value: Vector3
        :param event: 事件类型，默认为立即执行
        :type event: str
        :return: 操作是否成功
        :rtype: bool
        """
        ...
    
    def get_original_size(self) -> Vector3:
        """
        获取模型的原始尺寸。
        
        :return: 模型的原始尺寸(宽,高,深)
        :rtype: Vector3
        """
        ...
    
    def set_original_size(self, value: Vector3, event: str = APIEvent.NOW) -> bool:
        """
        设置模型的原始尺寸。
        
        :param value: 新的原始尺寸值
        :type value: Vector3
        :param event: 事件类型，默认为立即执行
        :type event: str
        :return: 操作是否成功
        :rtype: bool
        """
        ...
    
    def get_object_type(self) -> D5ApiActorType:
        """
        获取模型的对象类型。
        
        :return: 模型的对象类型
        :rtype: D5ApiActorType
        """
        ...
    


# 在类加载时动态生成getter和setter方法
D5Model._generate_methods()


